#include <iostream>
#include <functional>
#include <memory>
#include <string>
#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "CalCulate.hpp"
using namespace protocol_ns;
using namespace std;

void Usage(string proc)
{
    cout << "Usage:" << proc << " server-port" << endl;
}
using callback_t = function<Response(const Request &req)>;
// 计算服务
class Service
{
public:
    Service(callback_t cb)
        : _cb(cb)
    {
    }
    // 5.给成功连接的客户端提供服务
    void ServiceHelper(socket_sptr sockptr, InetAddr client)
    {
        int sockfd = sockptr->SockFd();
        string clientaddr = "[" + client.Ip() + ":" + to_string(client.Port()) + "-sockfd:" + to_string(sockfd) + "]# ";
        cout << "获取了一个新的连接-ip地址:" << client.Ip().c_str() << " 端口号:" << client.Port() << endl;
        string inbuffer;
        sleep(5);
        while (true)
        {
            sleep(5);
            // 1.读取数据
            Request req;
            int n = sockptr->Recv(&inbuffer); // 接收信息
            if (n < 0)
            {
                // 读取失败或者客户端退出
                cout << "客户端:" << clientaddr << " 退出" << endl;
                break;
            }
            cout << "服务器收到的信息：" << inbuffer << endl;

            // 获取有效信息
            // 2.检查报文完整度
            string package;
            while (true)
            {
                cout << "inbuffer:" << inbuffer << endl;
                package = Decode(inbuffer);
                if (package.empty() == true)
                {
                    break;
                }
                // 此时，获取到的有效信息就是完整的
                cout << "服务器拿到的有效信息：" << package << endl;

                // 3.反序列化
                req.UnSerialize(package); // 反序列化

                // 4.处理业务
                Response resp = _cb(req);

                // 5.将业务处理的结果序列化
                string send_str;
                resp.Serialize(&send_str);
                cout << "服务器处理结果序列化：" << send_str << endl;

                // 6.添加报头
                send_str = Encode(send_str);
                cout << "服务器添加完报头" << send_str << endl;

                // 7.发送报文
                sockptr->Send(send_str);
            }
        }
    }

private:
    callback_t _cb;
};

//./TcpServer 8888
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    uint16_t port = stoi(argv[1]); // 拿到端口号
    Calculate cal;
    Service calservice(std::bind(&Calculate::Excute, &cal, placeholders::_1));
    io_service_t service = bind(&Service::ServiceHelper, &calservice, placeholders::_1, placeholders::_2);
    unique_ptr<TcpServer> tsvr = make_unique<TcpServer>(port, service);

    tsvr->Loop();
    return 0;
}
